package org.jeecg.modules.rooms.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.modules.business.entity.BusHotel;
import org.jeecg.modules.business.service.impl.BusHotelServiceImpl;
import org.jeecg.modules.kc.entity.KcDepositoryInGoods;
import org.jeecg.modules.kc.entity.KcGoods;
import org.jeecg.modules.kc.service.impl.KcDepositoryInGoodsServiceImpl;
import org.jeecg.modules.kc.service.impl.KcGoodsServiceImpl;
import org.jeecg.modules.rooms.DTO.CesGoodsDto;
import org.jeecg.modules.rooms.DTO.CesGoodsSearchDto;
import org.jeecg.modules.rooms.Vo.CesGoodsVo;
import org.jeecg.modules.rooms.entity.CesGoods;
import org.jeecg.modules.rooms.entity.CesGoodsUnit;
import org.jeecg.modules.rooms.entity.CesStockType;
import org.jeecg.modules.rooms.mapper.CesGoodsMapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品表 服务实现类
 * </p>
 *
 * @author fendo
 * @since 2023-03-13
 */
@Service
public class CesGoodsServiceImpl extends ServiceImpl<CesGoodsMapper, CesGoods> implements IService<CesGoods> {
    @Resource
    private CesGoodsMapper goodsMapper;

    @Resource
    private BusHotelServiceImpl busHotelService;

    @Resource
    private CesStockTypeServiceImpl stockTypeService;

    @Resource
    private CesGoodsUnitServiceImpl goodsUnitService;


    @Resource
    private CesGoodsSpecsServiceImpl specsService;
@Resource
private KcDepositoryInGoodsServiceImpl kcDepositoryInGoodsService;
@Resource
private KcGoodsServiceImpl kcGoodsService;

    /**
     * 查询商品库存
     * @param dto
     * @return
     */
    public Result fetchList(CesGoodsSearchDto dto) {
        QueryWrapper<CesGoods> queryWrapper = new QueryWrapper<>();
        if (!StringUtils.isBlank(dto.getSearch())) {
            String search = CommonUtils.escapeChar(dto.getSearch());
            queryWrapper.like(CesGoods.BAR_CODE, search);
        }
        if (!StringUtils.isBlank(dto.getName())) {
            String name=dto.getName().replaceAll("\\*","");
            queryWrapper.like(StrUtil.isNotEmpty(name), CesGoods.NAME, name);
        }
        if (dto.getTypeId()!=null){
            queryWrapper.eq(CesGoods.GOOD_TYPE,dto.getTypeId());
        }

        queryWrapper.eq(CesGoods.HOTEL_ID, dto.getHotelId());
        queryWrapper.eq(CesGoods.INVALID, false);
        queryWrapper.eq(CesGoods.ISTEMP,false);
        queryWrapper.orderByDesc(CesGoods.CREATAT);
        // 分页查询商品
        IPage<CesGoods> dataPage = goodsMapper.selectPage(new Page<>(dto.getPageNo().intValue(), dto.getPageSize().intValue()), queryWrapper);
        List<CesGoods> result = dataPage.getRecords();
        // 找出商品关联的所有酒店
        List<String> hotelIds = result.stream().map(v -> v.getHotelId()).collect(Collectors.toList());
        List<BusHotel> hotels = busHotelService.findHotelsByIds(hotelIds);
        // 找出商品关联的所有商品类型
        List<String> typeIds = result.stream().map(v -> v.getGoodType()).collect(Collectors.toList());
        List<CesStockType> typeList = stockTypeService.fetchByIds(typeIds);
        // 找出商品关联的所有商品单位
        List<String> unitIds = result.stream().map(v -> v.getGoodUnit()).collect(Collectors.toList());
        List<CesGoodsUnit> unitList = goodsUnitService.fetchByIds(unitIds);
        List<CesGoodsVo> voList = new ArrayList<>();
        result.forEach(v -> {
            CesGoodsVo vo = new CesGoodsVo();
            BeanUtil.copyProperties(v, vo);
            Optional<BusHotel> busHotelOptional = hotels.stream().filter(c -> c.getId().equals(v.getHotelId())).findFirst();
            busHotelOptional.ifPresent(busHotel -> vo.setHotelName(busHotel.getName()));
            Optional<CesStockType> typeOptional = typeList.stream().filter(c -> c.getId().equals(v.getGoodType())).findFirst();
            typeOptional.ifPresent(cesStockType -> vo.setTypeName(cesStockType.getName()));
            Optional<CesGoodsUnit> unitOptional = unitList.stream().filter(c -> c.getId().equals(v.getGoodUnit())).findFirst();
            unitOptional.ifPresent(cesGoodsUnit -> vo.setUnitName(cesGoodsUnit.getName()));
            if (v.getIsStock() && ObjectUtils.isNotEmpty(v.getDepositoryInGoodsId())) {
                KcDepositoryInGoods kcDepositoryInGoods = kcDepositoryInGoodsService.getById(v.getDepositoryInGoodsId());
                if (kcDepositoryInGoods != null) {
                    KcGoods kcGoods = kcGoodsService.getById(kcDepositoryInGoods.getGoodsId());
                    if (kcGoods != null) {
                        vo.setStockGoodsName(kcGoods.getName());
                    }
                }
            }
            voList.add(vo);
        });
        Map<String, Object> map = new HashedMap();
        map.put("records", voList);
        map.put("total", dataPage.getTotal());
        return Result.OK(map);
    }

    /**
     * 查询商品列表
     * @param dto
     * @return
     */
    public Result queryList(CesGoodsSearchDto dto) {
        QueryWrapper<CesGoods> queryWrapper = new QueryWrapper<>();
        if (!StringUtils.isBlank(dto.getSearch())) {
            String search = CommonUtils.escapeChar(dto.getSearch());
            queryWrapper.or().like(CesGoods.BAR_CODE, search);
            queryWrapper.or().like(CesGoods.NAME, search);
        }
        if (!StringUtils.isBlank(dto.getTypeId())) {
            String typeId = CommonUtils.escapeChar(dto.getTypeId());
            QueryWrapper<CesStockType> queryWrapper_CesStockType = new QueryWrapper<CesStockType>();
            queryWrapper_CesStockType.eq("parent_id",typeId);
            List<CesStockType> typeList = stockTypeService.list(queryWrapper_CesStockType);
            if (typeList != null && typeList.size() > 0){
                String types = "";
                for (CesStockType item : typeList){
                    types = types+item.getId()+",";
                }
                queryWrapper.in(CesGoods.GOOD_TYPE, Arrays.asList(types.split(",")));
            }else{
                queryWrapper.like(CesGoods.GOOD_TYPE, typeId);
            }

        }
        queryWrapper.eq(CesGoods.HOTEL_ID, dto.getHotelId());
        queryWrapper.eq(CesGoods.INVALID, false);
        queryWrapper.orderByDesc(CesGoods.CREATAT);

        List<CesGoods> result = goodsMapper.selectList(queryWrapper);
        List<String> hotelIds = result.stream().map(v -> v.getHotelId()).collect(Collectors.toList());
        List<BusHotel> hotels = busHotelService.findHotelsByIds(hotelIds);
        List<String> typeIds = result.stream().map(v -> v.getGoodType()).collect(Collectors.toList());
        List<CesStockType> typeList = stockTypeService.fetchByIds(typeIds);
        List<String> unitIds = result.stream().map(v -> v.getGoodUnit()).collect(Collectors.toList());
        List<CesGoodsUnit> unitList = goodsUnitService.fetchByIds(unitIds);
        List<CesGoodsVo> voList = new ArrayList<>();
        result.forEach(v -> {
            CesGoodsVo vo = new CesGoodsVo();
            BeanUtil.copyProperties(v, vo);
            Optional<BusHotel> busHotelOptional = hotels.stream().filter(c -> c.getId().equals(v.getHotelId())).findFirst();
            if (busHotelOptional.isPresent()) {
                vo.setHotelName(busHotelOptional.get().getName());
            }
            Optional<CesStockType> typeOptional = typeList.stream().filter(c -> c.getId().equals(v.getGoodType())).findFirst();
            if (typeOptional.isPresent()) {
                vo.setTypeName(typeOptional.get().getName());
            }
            Optional<CesGoodsUnit> unitOptional = unitList.stream().filter(c -> c.getId().equals(v.getGoodUnit())).findFirst();
            if (unitOptional.isPresent()) {
                vo.setUnitName(unitOptional.get().getName());
            }
            if (v.getIsStock() && ObjectUtils.isNotEmpty(v.getDepositoryInGoodsId())) {
                KcDepositoryInGoods kcDepositoryInGoods = kcDepositoryInGoodsService.getById(v.getDepositoryInGoodsId());
                if (kcDepositoryInGoods != null) {
                    KcGoods kcGoods = kcGoodsService.getById(kcDepositoryInGoods.getGoodsId());
                    if (kcGoods != null) {
                        vo.setStockGoodsName(kcGoods.getName());
                    }
                }
            }
            vo.setNumber(Double.valueOf(0));
            voList.add(vo);
        });
        return Result.OK(voList);
    }

    /**
     * 创建商品
     * @param dto
     * @return
     */
    public Result create(CesGoodsDto dto){
        //不能有相同条码的数据
        QueryWrapper<CesGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(CesGoods.BAR_CODE,dto.getBarCode());
        queryWrapper.eq(CesGoods.INVALID,false);
        queryWrapper.eq(CesGoods.HOTEL_ID,dto.getHotelId());
        //查询
        CesGoods exitGoods = goodsMapper.selectOne(queryWrapper);
        if(!ObjectUtils.isEmpty(exitGoods)) return Result.error("该条码已有!");

        CesGoods goods = new CesGoods();
        BeanUtil.copyProperties(dto,goods);
        goods.setCreatAt(LocalDateTime.now());
        goods.setUpdateAt(LocalDateTime.now());
        goodsMapper.insert(goods);
        return Result.OK("保存成功!");
    }


    /**
     * 修改
     * @param dto
     * @return
     *
     */
    public Result modify(CesGoodsDto dto){
        CesGoods goods = goodsMapper.selectOne(Wrappers.<CesGoods>lambdaQuery().eq(CesGoods::getId,dto.getId()).eq(CesGoods::getInvalid,false));
        if(ObjectUtils.isEmpty(goods)) return Result.error("商品数据未找到!");
        //不能有相同条码的数据
        QueryWrapper<CesGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(CesGoods.BAR_CODE,dto.getBarCode());
        queryWrapper.eq(CesGoods.INVALID,false);
        queryWrapper.eq(CesGoods.HOTEL_ID,dto.getHotelId());
        queryWrapper.ne(CesGoods.ID,dto.getId());
        //查询
        CesGoods exitGoods = goodsMapper.selectOne(queryWrapper);
        if(!ObjectUtils.isEmpty(exitGoods)) return Result.error("该条码已有!");

        BeanUtil.copyProperties(dto,goods,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        goods.setUpdateAt(LocalDateTime.now());
        goodsMapper.updateById(goods);
        return Result.ok("修改成功!");
    }


    public Result delete(String id,String hotelId){
        CesGoods goods = goodsMapper.selectOne(Wrappers.<CesGoods>lambdaQuery().eq(CesGoods::getId,id).eq(CesGoods::getHotelId,hotelId).eq(CesGoods::getInvalid,false));
        if(ObjectUtils.isEmpty(goods)) return Result.error("商品数据未找到!");
        goods.setUpdateAt(LocalDateTime.now());
        goods.setInvalid(true);
        goodsMapper.updateById(goods);
        return Result.ok("删除成功!");
    }

    public Result delBatch(List<String> ids){
        if(CollectionUtil.isEmpty(ids)) return Result.ok("删除成功!");
        List<CesGoods> goods = goodsMapper.selectBatchIds(ids);
        goods.forEach(good -> {
            good.setUpdateAt(LocalDateTime.now());
            good.setInvalid(true);
        });
        updateBatchById(goods);
        return Result.ok("删除成功!");
    }


    /**
     * 查询酒店中的商品
     * @param id
     * @param hotelId
     * @return
     */
    public CesGoods fetchByIdAndHotelId(String id,String hotelId){
        if(StringUtils.isBlank(id) || StringUtils.isBlank(hotelId)) return null;
        return goodsMapper.selectOne(Wrappers.<CesGoods>lambdaQuery().eq(CesGoods::getHotelId,hotelId).eq(CesGoods::getId,id).eq(CesGoods::getInvalid,false));
    }


    /**商品退货*/
    public void saleReturn(KcDepositoryInGoods depositoryInGoods,String originalOrderId){
        KcDepositoryInGoods kcDepositoryInGoods = kcDepositoryInGoodsService.getOne(Wrappers.<KcDepositoryInGoods>lambdaQuery()
                .eq(KcDepositoryInGoods::getGoodsId, depositoryInGoods.getGoodsId())
                .eq(KcDepositoryInGoods::getFeeId, originalOrderId)
                .orderByDesc(KcDepositoryInGoods::getCreateTime).last("limit 1"));
        if (kcDepositoryInGoods == null){
            throw new JeecgBootException("未找到出库记录");
        }
        depositoryInGoods.setDepositoryId(kcDepositoryInGoods.getDepositoryId());
        CesGoods goods = getById(depositoryInGoods.getGoodsId());
        if (goods == null) {
            throw new JeecgBootException("未找到商品");
        }
        goods.setInventory(goods.getInventory() + depositoryInGoods.getNum());
        kcDepositoryInGoodsService.save(depositoryInGoods);
        updateById(goods);
    }







}
